package com.xneure.utils.bean;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import com.xneure.utils.ObjectUtil;
import com.xneure.utils.exception.ParseException;

public class ClassInfo{
	// 封装属性的set方法
	protected Object bean;
	private Class<?> cls;
	protected List<Class<?>> clsList = new ArrayList<Class<?>>();
	protected Map<String,Method> methods = new LinkedHashMap<String,Method>();
	protected Map<String,Field> fields = new LinkedHashMap<String,Field>();
	protected boolean retainTransient = false;

	public ClassInfo(Object obj){
		this(obj.getClass());
		setObject(obj);
	}

	public ClassInfo(Class<?> cls){
		updataObject(cls);
	}

	public void setMethodValue(String field,Object value){
		fillValue(field,value);
	}

	public void updataObject(Class<?> cls){
		if(null == cls){
			return;
		}
		boolean isDate = Date.class.isAssignableFrom(cls) || java.sql.Date.class.isAssignableFrom(cls);
		if(Number.class.isAssignableFrom(cls) || isDate || Object.class.equals(cls) || cls.isArray()){
			throw new ParseException("不支持基本数据类型。");
		}
		if(null != cls && cls.getClass().equals(cls) == false){
			this.cls = cls;
			Class<?> class1 = cls;
			clsList.clear();
			clsList.add(class1);
			loadMethodAndField(class1);
			while(class1.equals(Object.class) == false && class1.getSuperclass().equals(Object.class) == false){
				class1 = class1.getSuperclass();
				loadMethodAndField(class1);
				clsList.add(class1);
			}
		}
	}

	public void setObject(Object obj){
		if(cls.equals(obj.getClass())){
			this.bean = obj;
		}else{
			if(cls.equals(ObjectUtil.peelingCGLIB(obj.getClass()))){
				this.bean = obj;
				return;
			}
			throw new RuntimeException("当前对象类型与初始类型不匹配:" + obj.getClass().getName());
		}
	}

	protected void loadMethodAndField(Class<?> cls){
		if(cls.equals(Object.class)){
			return;
		}
		cls = ObjectUtil.peelingCGLIB(cls);
		for(Method m:cls.getMethods()){
			if(methods.containsKey(m.getName()) == false){
				methods.put(m.getName(),m);
			}
		}
		for(Field f:cls.getDeclaredFields()){
			if(retainTransient == false){
				if(Modifier.isTransient(f.getModifiers())){
					continue;
				}
			}
			if(fields.containsKey(f.getName()) == false){
				fields.put(f.getName(),f);
			}
		}
	}

	public Field[] getFields(){
		return fields.values().toArray(new Field[fields.size()]);
	}

	public int getFieldSize(){
		return fields.size();
	}

	public String[] getFieldNames(){
		return fields.keySet().toArray(new String[fields.size()]);
	}

	@SuppressWarnings("unchecked")
	public <T> T getFieldValue(String field){
		char[] cs = field.toCharArray();
		cs[0] = Character.toUpperCase(cs[0]);
		Method method = getMethod("get" + String.valueOf(cs));
		if(null != method){
			try{
				return (T)method.invoke(bean);
			}catch(Exception e){
				return null;
			}
		}else{
			Field fd = getField(field);
			if(null != fd){
				boolean flag = fd.isAccessible();
				fd.setAccessible(true);
				try{
					return (T)fd.get(this.bean);
				}catch(Exception e1){
					return null;
				}finally{
					fd.setAccessible(flag);
				}
			}else{
				return null;
			}
		}
	}

	public Method getMethod(String field){
		return methods.get(field);
	}

	public Map<String,Method> getMethods(){
		return methods;
	}

	public Field getField(String field){
		if(null != fields){
			return fields.get(field);
		}else{
			return null;
		}
	}

	public Object getMethodValue(Object obj,String mName){
		Method m = getMethod(mName);
		try{
			if(null != m){
				return m.invoke(obj);
			}
		}catch(Exception e){
		}
		return null;
	}

	/**
	 * 为对象赋值， values为给属性要赋的值 Map<String,Object> 名称 值
	 */
	public void setMethodValues(Map<String,Object> values){
		try{
			// 属性赋值
			for(Map.Entry<String,Object> entry:values.entrySet()){
				String name = entry.getKey();
				Object value = entry.getValue();
				name = name.trim();
				fillValue(name,value);
			}
		}catch(Exception e){
			e.printStackTrace();
		}
	}

	/**
	 * 为赋值对象， values为给属性要赋的值 Map<String,Object> 名称 值
	 */
	public Map<String,Object> getFieldValues(){
		try{
			// 属性赋值
			Map<String,Object> values = new HashMap<String,Object>(fields.size());
			for(Field fd:fields.values()){
				String name = fd.getName();
				values.put(name,getFieldValue(name));
			}
			return values;
		}catch(Exception e){
		}
		return null;
	}

	/**
	 * 将字符串值转换为合适的值填充到对象的指定域
	 * 
	 * @param field 需要填充的域
	 * @param value 字符串值
	 */
	public void fillValue(String field,Object value){
		try{
			char[] cs = field.toCharArray();
			cs[0] = Character.toUpperCase(cs[0]);
			Method m = methods.get("set" + String.valueOf(cs));
			if(m.getParameterTypes()[0].isAssignableFrom(GUID.class) && value instanceof String){
				value = GUID.valueOf((String)value);
			}else{
				value = ObjectUtil.convertValue(value,m.getParameterTypes()[0]);
			}
			m.invoke(this.bean,value);
		}catch(Exception e){
			Field f = getField(field);
			if(null != f){
				boolean flag = f.isAccessible();
				f.setAccessible(true);
				try{
					f.set(this.bean,value);
				}catch(Exception e1){
				}finally{
					f.setAccessible(flag);
				}
			}
		}
	}
}
